package strategy;

import java.util.List;

import root.friendship.Friendship;
import root.historic.AmizadeListener;
import root.item.Item;
import root.item.PublicarPedido;
import root.user.User;
import exceptions.FriendshipDoesNotExist;
import exceptions.InvalidAtributException;
import exceptions.InvalidUserException;
import exceptions.ItemDoesNotExist;
import exceptions.YouAreAlreadyFriends;
import exceptions.YouHaveAlreadyRequestedFriendship;
import exceptions.YouHaventReceivedARequest;

/**
 * Classe gerenciadora de amizades.
 * Encarregada das operacoes sobre
 * amizades entre usuarios.
 * Utiliza o padrao Expert.
 */
public interface GerenciadorAmizadeIF {
	/**
	 * Adiciona os listeners para o gerenciador de amizades 
	 * @param listener
	 */
	public void addListener(AmizadeListener listener);
	/**
	 * Retorna uma lista contendo os amigos de determinado usuario.
	 * @param request
	 * 	Usuário que terá a lista de amigos retornada.
	 * @return
	 */
	public List<User> getFriends();
	
	/**
	 * Uso isso pra os testes
	 * @param request
	 * @return
	 */
	public String getFriendsStringMode();
	
	/**
	 * Verifies if a has a pending request to b
	 * @param a
	 * @param b
	 * @return
	 */
	public boolean hasPendingRequest(User location);
	
	/**
	 * Verifies if a is friend of b
	 * @param a
	 * @param b
	 * @return
	 */
	public boolean isFriend(User location);
	
	/**
	 * Faz um pedido de amizade de A para B.
	 * @param requester
	 * 	A
	 * @param target
	 *  B
	 * @throws YouHaveAlreadyRequestedFriendship
	 *  Se A ja pediu pra ser amigo de B, nao deixo pedir novamente
	 * @throws YouAreAlreadyFriends
	 * 	Se A e B ja sao amigos, nao faz sentido pedir novamente
	 * @throws InvalidUserException
	 * 	Se A ou B forem nulls
	 *  
	 */
	public void requestFriendShip(GerenciadorAmizadeIF gAmizadeRequester) throws YouHaveAlreadyRequestedFriendship, YouAreAlreadyFriends, InvalidUserException;


	/**
	 * Da Deny em um Request
	 * @param requester
	 * 	O cara que vai dar o Deny
	 * @param target
	 *  O cara que pediu inicialmente a amizade
	 * @throws YouHaventReceivedARequest
	 *  Se "Target" nao tem uma solicitacao pendente pra "Requester", nao faz sentido ele negar
	 * @throws YouAreAlreadyFriends
	 *  Pode ser que essa excecao nunca seja executada, ja que se eles ja sao amigos, nao teria
	 *  solicitacao pendente sobrando, entretanto eu checo mesmo assim.(Ele talvez caia na excecao
	 *  de cima).
	 * @throws InvalidUserException
	 *  Se Requester ou Target forem null
	 */
	public void denyFriendship(GerenciadorAmizadeIF gerenciador) throws YouHaventReceivedARequest, YouAreAlreadyFriends, InvalidUserException;
	
	/**
	 * Da Accept em um Request
	 * @param requester
	 * 	O cara que vai dar o Accept
	 * @param target
	 *  O cara que pediu inicialmente a amizade
	 * @throws YouHaventReceivedARequest
	 *  Se "Target" nao tem uma solicitacao pendente pra "Requester", nao faz sentido ele aceitar
	 * @throws YouAreAlreadyFriends
	 *  Pode ser que essa excecao nunca seja executada, ja que se eles ja sao amigos, nao teria
	 *  solicitacao pendente sobrando, entretanto eu checo mesmo assim.(Ele talvez caia na excecao
	 *  de cima).
	 * @throws InvalidUserException
	 *  Se Requester ou Target forem null
	 */
	public void acceptFriendship(GerenciadorAmizadeIF gerenciador) throws YouHaventReceivedARequest, YouAreAlreadyFriends, InvalidUserException;
	
	/**
	 * Deleta o relacionamento entre dois usuarios
	 * @param a
	 * 	Usuario 1
	 * @param b
	 * 	Usuario 2
	 * @throws FriendshipDoesNotExist
	 */
	public void eraseFriendship(GerenciadorAmizadeIF gerenciador) throws FriendshipDoesNotExist;
	
	/**
	 * Retorna quem pediu pra ser amigo de a
	 * @param a
	 * @return
	 */
	public String getFriendshipRequestsStringMode();
	
	public String getFriendshipStringMode();
	
	/**
	 * Retorna uma lista contendo os usuarios que pediram
	 * para ser amigo de determinaod usuario
	 * @param a
	 * 	Usuario que terá a lista de usuários que querem ser amigos dele
	 * retornada
	 * @return
	 */
	public List<User> getFriendshipRequests();	
	/**
	 * 
	 * @param itemId id do item para o qual ele irá pesquisar 
	 * @return
	 * @throws ItemDoesNotExist
	 */
	public Item getItem(String itemId) throws ItemDoesNotExist;
	
	/**
	 * Retona um dado pedido para um determinado ID
	 * @param pedidoId id do pedido a ser retornado
	 * @return
	 * @throws InvalidAtributException
	 */
	public PublicarPedido getPedidoItem(String pedidoId) throws InvalidAtributException;
	
	public User getOwner();
	
	public void disparaAmizadeAprovada(User user);
	
	public void addFriendship(Friendship f);
	
	public void removeFriendship(Friendship f);
	
}